package com.zhiche.wms.service.base.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import com.zhiche.wms.core.supports.BaseException;
import com.zhiche.wms.core.supports.enums.SysSourceEnum;
import com.zhiche.wms.core.supports.enums.TableStatusEnum;
import com.zhiche.wms.core.utils.SnowFlakeId;
import com.zhiche.wms.domain.mapper.base.StoreLocationMapper;
import com.zhiche.wms.domain.model.base.StoreArea;
import com.zhiche.wms.domain.model.base.StoreLocation;
import com.zhiche.wms.domain.model.base.Storehouse;
import com.zhiche.wms.dto.inbound.StoreAreaAndLocationDTO;
import com.zhiche.wms.service.base.IStoreAreaService;
import com.zhiche.wms.service.base.IStoreLocationService;
import com.zhiche.wms.service.base.IStorehouseService;
import com.zhiche.wms.service.sys.IUserService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * <p>
 * 储位配置 服务实现类
 * </p>
 *
 * @author qichao
 * @since 2018-06-08
 */
@Service
public class StoreLocationServiceImpl extends ServiceImpl<StoreLocationMapper, StoreLocation> implements IStoreLocationService {
    private static final Logger LOGGER = LoggerFactory.getLogger(StoreLocationServiceImpl.class);
    @Autowired
    private SnowFlakeId snowFlakeId;

    @Autowired
    private IStorehouseService storehouseService;

    @Autowired
    private IStoreAreaService storeAreaService;
    @Autowired
    private IUserService userService;

    @Override
    public List<StoreLocation> listUsableLocation(Long storeHouseId) {
        return baseMapper.selectUsableLocations(storeHouseId);
    }

    @Override
    public List<StoreLocation> listUsableLocationByType(Long storeHouseId, String type) {
        return baseMapper.selectUsableLocationsByType(storeHouseId, type);
    }

    @Override
    public StoreLocation getUsableLocation (Long storeHouseId) {
        LOGGER.info("仓库storeHouseId ： {} 得到可用库存", storeHouseId);
        return baseMapper.selectFirstUsableLocation(storeHouseId);
    }

    @Override
    public Page<StoreLocation> getUsableLocationByPage(Page<StoreLocation> page) {
        Map<String, Object> condition = page.getCondition();
        Wrapper<StoreLocation> ew = new EntityWrapper<>();
        if (condition.containsKey("storeHouseId") && Objects.nonNull(condition.get("storeHouseId"))) {
            ew.eq("store_house_id", condition.get("storeHouseId"));
        }
        if (condition.containsKey("key") && Objects.nonNull(condition.get("key"))) {
            ew.like("name", String.valueOf(condition.get("key")));
        }
        if (condition.containsKey("storeAreaName") && Objects.nonNull(condition.get("storeAreaName"))) {
            ew.like("store_area_name", String.valueOf(condition.get("storeAreaName")));
        }
        if (condition.containsKey("type") && Objects.nonNull(condition.get("type"))) {
            ew.eq("type", condition.get("type"));
        }
        if (condition.containsKey("status") && Objects.nonNull(condition.get("status"))) {
            ew.eq("status", condition.get("status"));
        }
        ew.orderBy("id", false);
        List<StoreLocation> locDTOList;
        if (StringUtils.isEmpty((String) condition.get("oprType"))) {
            locDTOList= baseMapper.selectLocationsByPage(page, ew);
        }else {
            locDTOList= baseMapper.selectLocationsByAppPage(page, ew);
        }

        if (Objects.isNull(locDTOList) || locDTOList.size() <= 0) {
            if (page.getCurrent() > 1) {
                throw new BaseException("无更多库位");
            } else {
                throw new BaseException("无相关库位");
            }
        }
        page.setRecords(locDTOList);
        return page;
    }

    @Override
    public StoreLocation getUsableLocationByType(Long storeHouseId, String type) {
        return baseMapper.selectFirstUsableLocationByType(storeHouseId, type);
    }

    @Override
    public StoreLocation getUsableLocationByAreaType(Long storeHouseId, Long areaId, String type) {
        return baseMapper.selectFirstUsableLocationByAreaType(storeHouseId,areaId,type);
    }

    @Override
    public StoreLocation selectLocationByLocationId(Long locationId) {
        return baseMapper.selectLocationByLocationId(locationId);
    }

    @Override
    public List<StoreAreaAndLocationDTO> selectAllLocations(Map<String, String> condition) {
        return baseMapper.selectAllLocations(condition);
    }

    @Override
    public int getCountByCodeName(StoreLocation storeLocation) {
        if (Objects.isNull(storeLocation) || Objects.isNull(storeLocation)) {
            throw new BaseException("参数不能为空");
        }
        if (storeLocation.getStoreHouseId() == null || StringUtils.isBlank(storeLocation.getStoreHouseId().toString())) {
            throw new BaseException("仓库id不能为空");
        }
        if (storeLocation.getStoreAreaId() == null || StringUtils.isBlank(storeLocation.getStoreAreaId().toString())) {
            throw new BaseException("库区id不能为空");
        }
        if (StringUtils.isBlank(storeLocation.getCode())) {
            throw new BaseException("库位编码不能为空");
        }
        if (StringUtils.isBlank(storeLocation.getName())) {
            throw new BaseException("库位名称不能为空");
        }
        Wrapper<StoreLocation> ew = new EntityWrapper<>();
        ew.eq("store_house_id", storeLocation.getStoreHouseId().toString());
        if(StringUtils.isNotEmpty(storeLocation.getStoreAreaId().toString())){
            ew.eq("store_area_id", storeLocation.getStoreAreaId().toString());
        }
        ew.andNew().eq("code", storeLocation.getCode()).or().eq("name", storeLocation.getName());
        int count = this.baseMapper.getCountByCode(ew);
        return count;
    }

    @Override
    public Map<String, JSONArray> saveImportLocation(String data) {
        if (StringUtils.isBlank(data)) {
            throw new BaseException("导入数据为空");
        }
        JSONObject jsonObject = JSONObject.parseObject(data);
        String paramStoreHouseId = jsonObject.getString("storeHouseId");
        if(StringUtils.isEmpty(paramStoreHouseId)){
            throw new BaseException("仓库id为空");
        }
        JSONArray arrayRows = JSONObject.parseArray(jsonObject.getString("rows"));
        JSONArray arrayHeader = JSONObject.parseArray(jsonObject.getString("header"));
        if (CollectionUtils.isEmpty(arrayHeader)) {
            throw new BaseException("导入数据为空");
        }
        if (CollectionUtils.isEmpty(arrayRows)) {
            throw new BaseException("导入数据为空");

        }
        if (!arrayHeader.get(arrayHeader.size() - 1).equals("备注")) {
            arrayHeader.add("导入结果");
            arrayHeader.add("备注");
        }

        HashMap<String, Long> whCache = Maps.newHashMap();
        Map<String, JSONArray> map = new HashMap<>();

        for (int i = 0; i < arrayRows.size(); i++) {
            checkAndInsertData(arrayRows, whCache, i,paramStoreHouseId);
        }
        map.put("header", arrayHeader);
        map.put("rows", arrayRows);
        return map;
    }

    private void checkAndInsertData(JSONArray arrayRows, HashMap<String, Long> whCache, int i,String storeHouseId) {
        StoreLocation location = new StoreLocation();
        location.setStoreHouseName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("仓库名称")) ?
                null : arrayRows.getJSONObject(i).getString("仓库名称").trim());
        location.setStoreAreaName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("库区名称")) ?
                null : arrayRows.getJSONObject(i).getString("库区名称").trim());
        location.setTypeByTypeName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("库位类型")) ?
                null : arrayRows.getJSONObject(i).getString("库位类型").trim());
        location.setCode(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("库位代码")) ?
                null : arrayRows.getJSONObject(i).getString("库位代码").trim());
        location.setName(StringUtils.isBlank(arrayRows.getJSONObject(i).getString("库位名称")) ?
                null : arrayRows.getJSONObject(i).getString("库位名称").trim());
        location.setMaxStorage(arrayRows.getJSONObject(i).getBigDecimal("最大库存"));
        location.setSort(arrayRows.getJSONObject(i).getInteger("排序"));

        StringBuilder sb = new StringBuilder();
        String storeHouseName = location.getStoreHouseName();
        String storeAreaName = location.getStoreAreaName();
        String type = location.getType();
        String code = location.getCode();
        String name = location.getName();
        if (StringUtils.isBlank(storeHouseName)) {
            sb.append("仓库名称为空;");
        }
        if (StringUtils.isBlank(storeAreaName)){
            sb.append("库区名称为空;");
        }
        if (StringUtils.isBlank(type)) {
            sb.append("库位类型为空;");
        }
        if ("0".equals(type)) {
            sb.append("库位类型不合法;");
        }
        if (StringUtils.isBlank(code)) {
            sb.append("库位代码为空;");
        }
        if (StringUtils.isBlank(name)) {
            sb.append("库位名称为空;");
        }
        //设置仓库id缓存map
        EntityWrapper<Storehouse> hwp = new EntityWrapper<>();
        hwp.eq("name", location.getStoreHouseName()).eq("status", TableStatusEnum.STATUS_10.getCode());
        Long houseId = whCache.get(location.getStoreHouseName());
        if (houseId == null) {
            List<Storehouse> storehouses = storehouseService.selectList(hwp);
            if (CollectionUtils.isNotEmpty(storehouses)) {
                whCache.put(location.getStoreHouseName(), storehouses.get(0).getId());
                houseId = storehouses.get(0).getId();
            } else {
                //未找到仓库--提示错误
                sb.append("未找到仓库名称").append(location.getStoreHouseName()).append("信息;");
            }
        }
        location.setStoreHouseId(houseId);

        Long areaId = null;
        if (houseId != null) {
            //查询库区
            EntityWrapper<StoreArea> awp = new EntityWrapper<>();
            awp.eq("store_house_id",houseId).eq("name", location.getStoreAreaName())
               .eq("status", TableStatusEnum.STATUS_10.getCode());
            List<StoreArea> areas = storeAreaService.selectList(awp);
            if (CollectionUtils.isNotEmpty(areas)) {
                areaId = areas.get(0).getId();
            }else{
                sb.append("未查询到对应仓库:").append(location.getStoreHouseName()).append("库区:").append(location.getStoreAreaName()).append("信息;");
            }
        }
        location.setStoreAreaId(areaId);

        //重复性校验
        int countByCode = 0;
        try {
            countByCode = getCountByCodeName(location);
        } catch (Exception e) {
            sb.append(e.getMessage());
        }
        if (countByCode >= 1){
            sb.append("库位代码").append(location.getCode()).append("或库位名称").append(location.getName()).append("已经存在;");
        }
        //查看导入仓库id是否和当前登录的仓库id是一致的
        if(!String.valueOf(houseId).equals(storeHouseId)){
            sb.append("导入仓库").append(houseId).append("与当前当前仓库").append(storeHouseId).append("不匹配;");
        }

        if (StringUtils.isNotBlank(sb)) {
            arrayRows.getJSONObject(i).put("导入结果", "失败");
            arrayRows.getJSONObject(i).put("备注", sb.toString());
        } else {
            try {
                StoreLocation insertLocation = new StoreLocation();
                insertLocation.setId(snowFlakeId.nextId());
                insertLocation.setStoreHouseId(whCache.get(location.getStoreHouseName()));
                insertLocation.setStoreAreaId(areaId);
                insertLocation.setType(location.getType());
                insertLocation.setCode(location.getCode());
                insertLocation.setName(location.getName());
                insertLocation.setMaxStorage(location.getMaxStorage());
                insertLocation.setSort(location.getSort());
                //设置状态为正常
                insertLocation.setStatus(TableStatusEnum.STATUS_10.getCode());
                insertLocation.setUserCreate(SysSourceEnum.IMPORT.getName());
                insertLocation.setUserModified(SysSourceEnum.IMPORT.getName());
                //导入库位
                if (insert(insertLocation)){
                    arrayRows.getJSONObject(i).put("导入结果", "成功");
                    arrayRows.getJSONObject(i).put("备注", "无");
                }else{
                    arrayRows.getJSONObject(i).put("导入结果", "失败");
                    arrayRows.getJSONObject(i).put("备注", "创建库位失败");
                }
            } catch (Exception e) {
                arrayRows.getJSONObject(i).put("导入结果", "系统异常");
                arrayRows.getJSONObject(i).put("备注", e.getMessage());
            }
        }
    }

    @Override
    public boolean updateStoreLocation(StoreLocation storeLocation) {
        Wrapper<StoreLocation> ew = new EntityWrapper<>();
        ew.eq("name",storeLocation.getName()).eq("store_house_id",storeLocation.getStoreHouseId())
                .ne("id",storeLocation.getId());
        int selectCount = selectCount(ew);
        if (selectCount > 0){
            throw new BaseException("库位名称已存在");
        }
        boolean updateById = updateById(storeLocation);
        return updateById;
    }

    @Override
    public StoreLocation queryUsableLocationByAreaId (Long storeHouseId, Long areaId) {
        LOGGER.info("仓库storeHouseId ： {} 得到可用库存", storeHouseId);
        return baseMapper.queryUsableLocationByAreaId(storeHouseId,areaId);
    }

    @Override
    public String queryAreaCodeDetail (String areaName, String locationName) {
        String locDetail = "";
        if (StringUtils.isNotBlank(areaName) && areaName.endsWith("区")) {
            locDetail = areaName.concat(locationName);
        } else if (StringUtils.isNotBlank(areaName) && !areaName.endsWith("区")) {
            locDetail = areaName.concat("区").concat(locationName);
        } else if (StringUtils.isBlank(areaName)) {
            locDetail = locationName;
        }
        return locDetail;
    }

}
